package com.lu.statistics.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import com.lu.statistics.common.auth.RedisClient;
import com.lu.statistics.common.config.ServerResponse;
import com.lu.statistics.common.constant.RedisConstant;
import com.lu.statistics.common.constant.ResponseCode;
import com.lu.statistics.common.utils.LoggerUtils;
import com.lu.statistics.entity.SysAppUser;
import com.lu.statistics.entity.SysFile;
import com.lu.statistics.entity.front.request.*;
import com.lu.statistics.entity.front.response.AppUserResponse;
import com.lu.statistics.entity.front.response.LoginResponse;
import com.lu.statistics.entity.send.SendSmsUtils;
import com.lu.statistics.exception.AccountDisabledException;
import com.lu.statistics.exception.UnknownAccountException;
import com.lu.statistics.fileService.FileUploadService;
import com.lu.statistics.service.AppUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Set;

@Api(value = "用户模块", tags = {"用户模块"})
@RestController
@RequestMapping("/api/user")
public class UserController {
    @Autowired
    private AppUserService userService;
    @Autowired
    private FileUploadService fileUploadService;
    @Autowired
    private RedisClient redisClient;

    @ApiOperation(value = "登录接口")
    @PostMapping("/login")
    public ServerResponse<LoginResponse> login(@RequestBody LoginRequest loginRequest) {
        LoginResponse loginResponse = new LoginResponse();
        SysAppUser user = userService.queryUserByUserNameAndPassword(loginRequest.getUserName(), loginRequest.getPassword());
        try {
            if (user != null) {
                StpUtil.setLoginId(user.getId());
                Set<String> permissions = userService.queryUserPermCodeListByUser(user.getId());
                loginResponse.setPermissionName(permissions);
                String token = StpUtil.getTokenInfo().getTokenValue();
                loginResponse.setToken(token);
                AppUserResponse userResponse = new AppUserResponse();
                String url = "/api/file/previewPhoto?fileFullPath=" + user.getAvatarUrl();
                userResponse.setAvatarUrl(url);
                BeanUtils.copyProperties(user, userResponse);
                loginResponse.setUser(userResponse);
                return ServerResponse.success(loginResponse, token);
            } else {
                return ServerResponse.error();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ServerResponse.error();
        }
    }

    @ApiOperation(value = "手机号登录")
    @PostMapping("/phoneLogin")
    public ServerResponse phoneLogin(@RequestBody PhoneLoginRequest request) {
        LoginResponse loginResponse = new LoginResponse();
        try {
            String key = RedisConstant.User.VERIFY_CODE + request.getTelephone();
            String oldCaptchaCode = redisClient.get(key);
            if (oldCaptchaCode != null && oldCaptchaCode.equals(request.getCaptcha().toString())) {
                SysAppUser user = userService.queryUserByPhone(request.getTelephone());
                if (user != null) {
                    StpUtil.setLoginId(user.getId());
                    Set<String> permissions = userService.queryUserPermCodeListByUser(user.getId());
                    loginResponse.setPermissionName(permissions);
                    String token = StpUtil.getTokenInfo().getTokenValue();
                    loginResponse.setToken(token);
                    AppUserResponse userResponse = new AppUserResponse();
                    String url = "/api/file/previewPhoto?fileFullPath=" + user.getAvatarUrl();
                    userResponse.setAvatarUrl(url);
                    BeanUtils.copyProperties(user, userResponse);
                    loginResponse.setUser(userResponse);
                    redisClient.del(key);
                    return ServerResponse.success(loginResponse, token);
                } else {
                    return ServerResponse.error(ResponseCode.VERIFY_CODE_ERROR);
                }
            } else {
                return ServerResponse.error(ResponseCode.VERIFY_CODE_ERROR);
            }
        } catch (UnknownAccountException e) {
            LoggerUtils.error(getClass(), "[sysAppUser phoneLogin]", e);
            return ServerResponse.error(ResponseCode.USER_NOT_EXISTS);
        } catch (AccountDisabledException e) {
            LoggerUtils.error(getClass(), "[sysAppUser phoneLogin]", e);
            return ServerResponse.error(ResponseCode.ACCOUNT_DISABLE);
        }
    }

    @ApiOperation(value = "用户注册", notes = "用户注册")
    @PostMapping(value = "/registerUser")
    public ServerResponse<String> registerUser(@RequestBody UserRegisterRequest request) {
        try {
            String key = RedisConstant.User.VERIFY_CODE + request.getTelephone();
            String oldCaptchaCode = redisClient.get(key);
            if (oldCaptchaCode != null && oldCaptchaCode.equals(request.getCaptcha().toString())) {
                SysAppUser user = new SysAppUser();
                user.setUsername(request.getTelephone());
                user.setTelephone(request.getTelephone());
                user.setPassword(request.getPassword());
                userService.createUser(user);
                redisClient.del(key);
            } else {
                return ServerResponse.error(ResponseCode.VERIFY_CODE_ERROR);
            }

        } catch (DuplicateKeyException e) {
            LoggerUtils.error(getClass(), "[sysAppUser registerUser]", e);
            return ServerResponse.error(ResponseCode.USER_EXISTS);
        } catch (Exception e) {
            LoggerUtils.error(getClass(), "[sysAppUser registerUser]", e);
            return ServerResponse.error(ResponseCode.ERROR);
        }
        return ServerResponse.success();
    }

    @ApiOperation(value = "重置密码", notes = "重置密码")
    @PostMapping(value = "/resetPassword")
    public ServerResponse<String> resetPassword(@RequestBody UserRegisterRequest request) {
        try {
            String key = RedisConstant.User.VERIFY_CODE + request.getTelephone();
            String oldCaptchaCode = redisClient.get(key);
            if (oldCaptchaCode != null && oldCaptchaCode.equals(request.getCaptcha().toString())) {
                SysAppUser user = new SysAppUser();
                user.setTelephone(request.getTelephone());
                user.setPassword(request.getPassword());
                userService.updatePasswordByPhone(user);
                redisClient.del(key);
            } else {
                return ServerResponse.error(ResponseCode.VERIFY_CODE_ERROR);
            }

        } catch (DuplicateKeyException e) {
            e.printStackTrace();
            LoggerUtils.error(getClass(), "[sysAppUser resetPassword]", e);
            return ServerResponse.error(ResponseCode.USER_EXISTS);
        } catch (Exception e) {
            e.printStackTrace();
            LoggerUtils.error(getClass(), "[sysAppUser resetPassword]", e);
            return ServerResponse.error(ResponseCode.ERROR);
        }
        return ServerResponse.success();
    }

    @ApiOperation(value = "验证用户手机号", notes = "验证用户手机号")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "query", required = true, name = "phone", value = "手机号", dataType = "string")})
    @GetMapping(value = "/validatePhone")
    public ServerResponse<String> validatePhone(String phone) throws Exception {
        int count = userService.queryUserCountByPhone(phone);
        if (count > 0) {
            return ServerResponse.success();
        } else {
            return ServerResponse.error();
        }
    }

    @ApiOperation(value = "获取手机号验证码（登录用）")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "query", required = true, name = "phone", value = "手机号", dataType = "string")})
    @GetMapping(value = "/verifyCode")
    public ServerResponse<String> getVerifyCode(String phone) throws Exception {
        int count = userService.queryUserCountByPhone(phone);
        if (count > 0) {
            Integer verifyCode = new SendSmsUtils().sendSms(phone);
            redisClient.set(RedisConstant.User.VERIFY_CODE + phone, verifyCode.toString(), 300);
            return ServerResponse.success();
        } else {
            return ServerResponse.error();
        }
    }

    @ApiOperation(value = "获取手机号验证码（注册用）")
    @ApiImplicitParams({@ApiImplicitParam(paramType = "query", required = true, name = "phone", value = "手机号", dataType = "string")})
    @GetMapping(value = "/verifyRegisterCode")
    public ServerResponse<String> verifyRegisterCode(String phone) throws Exception {
        int count = userService.queryUserCountByPhone(phone);
        if (count == 0) {
            Integer verifyCode = new SendSmsUtils().sendSms(phone);
            redisClient.set(RedisConstant.User.VERIFY_CODE + phone, verifyCode.toString(), 300);
            return ServerResponse.success();
        } else {
            return ServerResponse.error();
        }
    }

    @ApiOperation(value = "退出登录")
    @GetMapping("/logout")
    public ServerResponse<String> logout() {
        StpUtil.logout();
        return ServerResponse.success();
    }

    @ApiOperation(value = "更新用户", notes = "更新用户")
    @SaCheckLogin
    @PostMapping(value = "/updateUser")
    public ServerResponse<String> updateUser(@RequestBody UpdateUserRequest updateUser) {
        SysAppUser user = new SysAppUser();
        BeanUtils.copyProperties(updateUser, user);
        userService.updateUser(user);
        return ServerResponse.success();
    }

    @ApiOperation(value = "获取用户信息", notes = "获取用户信息")
    @GetMapping(value = "/userInfo")
    public ServerResponse<AppUserResponse> userInfo() throws Exception {
        Integer userId = Integer.parseInt(StpUtil.getLoginId().toString());
        SysAppUser appUser = userService.queryUserById(userId);
        AppUserResponse userResponse = new AppUserResponse();
        String url = "/api/file/previewPhoto?fileFullPath=" + appUser.getAvatarUrl();
        BeanUtils.copyProperties(appUser, userResponse);
        userResponse.setAvatarUrl(url);
        return ServerResponse.success(userResponse);

    }

    @ApiOperation(value = "上传头像", notes = "上传头像")
    @SaCheckLogin
    @PostMapping(value = "/uploadAvatar")
    @ResponseBody
    public ServerResponse<String> uploadAvatar(@RequestParam(value = "file") @RequestPart MultipartFile file, CreateFile createFile) {
        try {
            SysFile sysFile = new SysFile();
            sysFile.setFileNumber(createFile.getFileNumber());
            //返回原来的文件名在客户机的文件系统。
            sysFile.setFileName(file.getOriginalFilename());
            //返回文件的大小,以字节为单位。
            sysFile.setFileSize(file.getSize() / 1024.00f);
            Integer userId = Integer.parseInt(StpUtil.getLoginId().toString());
            sysFile.setCreateId(userId);
            sysFile.setFileType(createFile.fileType.name());
            //返回InputStream读取文件的内容
            SysFile sysFiles = fileUploadService.uploadFile(sysFile, file.getInputStream());
            if (sysFiles != null) {
                //修改用户头像信息
                SysAppUser user = new SysAppUser();
                user.setId(userId);
                user.setAvatarUrl(sysFiles.getFileFullPath());
                SysAppUser appUser = userService.updateAvatar(user);
                String url = "/api/file/previewPhoto?fileFullPath=" + appUser.getAvatarUrl();

                return ServerResponse.success(url);
            }
        } catch (IOException e) {
            LoggerUtils.error(getClass(), "[sysAppUser uploadAvatar]", e);
            return ServerResponse.errorMessage("文件上传失败，文件格式不正确！");
        } catch (DuplicateKeyException e) {
            LoggerUtils.error(getClass(), "[sysAppUser uploadAvatar]", e);
            return ServerResponse.errorMessage("文件已存在！");
        } catch (IllegalArgumentException e) {
            LoggerUtils.error(getClass(), "[sysAppUser uploadAvatar]", e);
            return ServerResponse.errorMessage("文件内容有空值！");
        } catch (Exception e) {
            LoggerUtils.error(getClass(), "[sysAppUser uploadAvatar]", e);
            return ServerResponse.errorMessage("文件上传失败，文件格式不正确！");
        }
        return ServerResponse.errorMessage("文件上传失败！");
    }
}
